package com.wuliang.generate.common.core.utils;

import com.wuliang.generate.common.core.basic.BaseVo;
import com.wuliang.generate.common.core.basic.BasicEntity;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @author WuLiang
 */
public class VoUtils {

    /**
     * 将VO对象格式化为实体类对象
     *
     * @param vo  基础VO对象
     * @param <T> 实体类对象
     * @return 实体类对象
     */
    public static <T extends BasicEntity> T voToEntity(BaseVo<T> vo) {
        // 获取泛型中的对象
        Type voType = vo.getClass().getGenericSuperclass();
        // 获取实体类对象格式
        Type entityType = ((ParameterizedType) voType).getActualTypeArguments()[0];
        // 转为实体类对象
        System.out.println(entityType.getClass().getSimpleName());
        return voToEntity(vo, (Class<T>) entityType);
    }

    /**
     * 将VO对象格式化为实体类对象
     *
     * @param baseVo      基础VO对象
     * @param entityClass 实体类对象的Class
     * @param <T>         实体类对象
     * @return 实体类对象
     */
    public static <T extends BasicEntity> T voToEntity(BaseVo<T> baseVo, Class<T> entityClass) {
        Map<String, Object> voMap = JsonUtils.objectToMap(baseVo);
        voMap.put("ID", invokeGetIdMethod(baseVo));
        return JsonUtils.mapToObject(voMap, entityClass);
    }

    public static <V extends BaseVo<? extends BasicEntity>> V entityToVo(BasicEntity entity) {
        return entityToVo(entity, null);
    }

    /**
     * 将实体类对象格式化为VO对象
     *
     * @param entity 实体类对象
     * @return Vo对象
     */
    public static <V extends BaseVo<? extends BasicEntity>> V entityToVo(BasicEntity entity, Class<V> voClass) {
        return JsonUtils.mapToObject(JsonUtils.objectToMap(entity), voClass);
    }

    public static <V extends BaseVo<?>> Boolean checkJoinParam(V vo, String... checkParamNameList) {
        List<String> fieldNameList = ClassUtils.getClassAllField(vo.getClass(), vo.getClass());
        for (String checkParamName : checkParamNameList) {
            if (fieldNameList.contains(checkParamName)) {
                Object invokeResult = ClassUtils.invokeGetterMethod(vo, checkParamName);
                if (invokeResult == null) {
                    return false;
                }
            }
            if (checkParamName.startsWith("searchKeywords")) {
                return vo.getSearchKeywords().get(checkParamName.substring(checkParamName.indexOf(".") + 1)) != null;
            }
        }
        return true;
    }

    /**
     * 调用 get 主键方法
     *
     * @param vo  前后端传输对象
     * @param <V> 参数上限规定
     * @return 主键值
     */
    public static <V extends BaseVo<? extends BasicEntity>> Object invokeGetIdMethod(V vo) {
        // 获取实体类对象名称
        String entityName = vo.getClass().getSimpleName();
        // 声明 业务+主键 名称
        String idFieldName = entityName.substring(0, entityName.length() - 2) + "Id";
        // 遍历传输对象中的私有字段
        for (Field declaredField : vo.getClass().getDeclaredFields()) {
            // 如果传输对象中的私有字段名称包含 业务+主键 名称，并且这两不相等的情况下
            if (idFieldName.toUpperCase().contains(declaredField.getName().toUpperCase()) &&
                !idFieldName.toUpperCase().equals(declaredField.getName().toUpperCase())) {
                // 将 传输对象中的字段首字母转换成大写后复制为主键名称
                idFieldName =
                        declaredField.getName().substring(0, 1).toUpperCase() + declaredField.getName().substring(1);
            }
        }
        // 声明  业务主键的 getter 方法名
        String getIdMethodName = "get" + entityName.substring(0, entityName.length() - 2) + "Id";
        try {
            // 声明 getter 方法对象
            Method method = vo.getClass().getDeclaredMethod(getIdMethodName);
            // 返回调用结果
            return method.invoke(vo);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

}
